package cn.soqi.xxljob.web.admin.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author lwd
 * @date 2021/7/13 10:27
 */
public class XxlJobUtils {

    private static Logger logger = LoggerFactory.getLogger(XxlJobUtils.class);
    private static RestTemplate restTemplate = new RestTemplate();

    private static String url="http://127.0.0.1:8080/xxl-job-admin";
    private static String cookie="";
    private static HttpHeaders reqheaders = new HttpHeaders();
    private static Map<String,Jobgroup> jobgroupMap = new HashMap<>();


    public static void init(String url,String userName,String password,String... appNames){
        XxlJobUtils.url = url;
        XxlJobUtils.login(userName,password);
        jobgroup(appNames);
    }

    /**
     * 新增/编辑任务
     * @return
     */
    public static XxlJobInfo addJob(String appName,String jobDesc, String cron,String rxecutorHandler,String executorParam
            ,String author,String alarmEmail){
        XxlJobInfo xxlJobInfo = new XxlJobInfo();
        Jobgroup jobgroup = jobgroupMap.get(appName);
        if(jobgroup == null){
            throw new RuntimeException("appName=" + appName + " 未配置,请在配置 appNames中添加" + appName);
        }
        xxlJobInfo.setJobGroup(jobgroup.getId());
        xxlJobInfo.setJobDesc(jobDesc);
        xxlJobInfo.setExecutorRouteStrategy(ExecutorRouteStrategy.FIRST);
        xxlJobInfo.setScheduleType(ScheduleType.CRON);
        xxlJobInfo.setGlueType(GlueType.BEAN);
        xxlJobInfo.setScheduleConf(cron);
        xxlJobInfo.setExecutorBlockStrategy(ExecutorBlockStrategy.SERIAL_EXECUTION);
        xxlJobInfo.setMisfireStrategy(MisfireStrategy.DO_NOTHING);
        xxlJobInfo.setExecutorHandler(rxecutorHandler);
        xxlJobInfo.setExecutorParam(executorParam);
        xxlJobInfo.setAuthor(author);
        xxlJobInfo.setAlarmEmail(alarmEmail);
        xxlJobInfo.setGlueRemark("java代码创建");
        xxlJobInfo.setExecutorFailRetryCount(0);
        return addJob(xxlJobInfo);
    }

    /**
     * 新增/编辑任务
     * @param xxlJobInfo
     * @return
     */
    public static XxlJobInfo addJob(XxlJobInfo xxlJobInfo){

        String path = "/jobinfo/add";
        String targetUrl = url + path;
        ResponseEntity<XxlRes> response = post(targetUrl, reqheaders, BeanUtils.beanToMap(xxlJobInfo), XxlRes.class);
        if(response.getBody().getCode() != 200){
            throw new XxlJobWebRequestException(response.getBody().getMsg(),response.getBody());
        }
        xxlJobInfo.setId(Integer.valueOf((String)response.getBody().getContent()));
        return xxlJobInfo;
    }

    /**
     * 查询
     * @param id
     * @return
     */
    public static XxlJobInfo getJob(int id){

        ResponseEntity<XxlJobInfoRes> xxlJobInfoRes = get(url + "/jobinfo/get?id=" + id,reqheaders,null,XxlJobInfoRes.class);
        if(xxlJobInfoRes.getBody().getCode() != 200){
            throw new XxlJobWebRequestException(xxlJobInfoRes.getBody().getMsg(),xxlJobInfoRes.getBody());
        }
        XxlJobInfo xxlJobInfo = xxlJobInfoRes.getBody().getContent();
        return xxlJobInfo;
    }

    /**
     * 更新任务
     * @param
     * @return
     */
    public static Boolean updateJob(int id,String cron){

        ResponseEntity<XxlJobInfoRes> xxlJobInfoRes = get(url + "/jobinfo/get?id=" + id,reqheaders,null,XxlJobInfoRes.class);
        if(xxlJobInfoRes.getBody().getCode() != 200){
            throw new XxlJobWebRequestException(xxlJobInfoRes.getBody().getMsg(),xxlJobInfoRes.getBody());
        }
        XxlJobInfo xxlJobInfo = xxlJobInfoRes.getBody().getContent();
        if(xxlJobInfo == null){
            return false;
        }
        xxlJobInfo.setScheduleConf(cron);
        String path = "/jobinfo/update";
        String targetUrl = url + path;
        ResponseEntity<XxlRes> response = post(targetUrl, reqheaders, BeanUtils.beanToMap(xxlJobInfo), XxlRes.class);
        if(response.getBody().getCode() != 200){
            throw new XxlJobWebRequestException(response.getBody().getMsg(),response.getBody());
        }
        return true;
    }

    /**
     * 启动定时
     * @param id
     * @return
     */
    public static Boolean startJob(int id){
        ResponseEntity<XxlRes> xxlJobInfoRes = get(url + "/jobinfo/start?id=" + id,reqheaders,null,XxlRes.class);
        if(xxlJobInfoRes.getBody().getCode() != 200){
            throw new XxlJobWebRequestException(xxlJobInfoRes.getBody().getMsg(),xxlJobInfoRes.getBody());
        }
        return true;
    }

    /**
     * 暂停
     * @param id
     * @return
     */
    public static Boolean stopJob(int id){
        ResponseEntity<XxlRes> xxlJobInfoRes = get(url + "/jobinfo/stop?id=" + id,reqheaders,null,XxlRes.class);
        if(xxlJobInfoRes.getBody().getCode() != 200){
            throw new XxlJobWebRequestException(xxlJobInfoRes.getBody().getMsg(),xxlJobInfoRes.getBody());
        }
        return true;
    }

    /**
     * 删除
     * @param id
     * @return
     */
    public static Boolean removeJob(int id){
        ResponseEntity<XxlRes> xxlJobInfoRes = get(url + "/jobinfo/remove?id=" + id,reqheaders,null,XxlRes.class);
        if(xxlJobInfoRes.getBody().getCode() != 200){
            throw new XxlJobWebRequestException(xxlJobInfoRes.getBody().getMsg(),xxlJobInfoRes.getBody());
        }
        return true;
    }



    /**
     * 执行器列表
     * @param appNames
     * @return
     */
    public static void jobgroup(String... appNames){

        for (String appName : appNames) {
            HashMap<String, Object> params = new HashMap<>();
            params.put("appname",appName);
            params.put("title","");
            params.put("start", 0);
            params.put("length", 10);
            String path = "/jobgroup/pageList";
            String targetUrl = url + path;
            ResponseEntity<Map> response = post(targetUrl, reqheaders, params, Map.class);
            Map body = response.getBody();
            Integer recordsFiltered = (Integer)body.get("recordsFiltered");
            if(recordsFiltered > 1){
                throw new XxlJobWebInitJobgroupException("执行器名称 appname=" + appName + " 在管理中心不止一个");
            }
            if(recordsFiltered == 1){
                Map<String,Object> data = (Map)((List)body.get("data")).get(0);
                Jobgroup jobgroup = new Jobgroup();
                jobgroup.setId((Integer) data.get("id"));
                jobgroup.setAppname((String) data.get("appname"));
                jobgroup.setTitle((String) data.get("title"));
//                jobgroup.setAddressType((Integer) data.get("addressType"));
//                jobgroup.setAddressList((String) data.get("addressList"));
//                jobgroup.setRegistryList((String) data.get("registryList"));
                jobgroup.setUpdateTime((String) data.get("updateTime"));
                jobgroupMap.put(appName,jobgroup);
                continue;
            }
            //执行器管理中心不存在
            throw new XxlJobWebInitJobgroupException("执行器名称 appname=" + appName + " 在管理中心不存在请登录后台添加");
        }
    }


    public static String login(String userName, String password){
        String path = "/login?userName="+userName+"&password="+password;
        String targetUrl = url + path;
        ResponseEntity<XxlRes> xxlResResponseEntity = post(targetUrl, null, null, XxlRes.class);
        if(xxlResResponseEntity.getBody().getCode() != 200){
            throw new XxlJobWebRequestException("xxljob admin login error " + xxlResResponseEntity.getBody().getMsg(),xxlResResponseEntity.getBody());
        }

        HttpHeaders resHeaders = xxlResResponseEntity.getHeaders();
        List<String> cookies = resHeaders.get("Set-Cookie");
        StringBuffer tmpcookies = new StringBuffer();
        for (String cookie : cookies) {
            tmpcookies.append(cookie + ";");
        }
        cookie = tmpcookies.toString();
        reqheaders.set("Cookie",cookie);
        reqheaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        return cookie;
    }


    /**
     * 发送http请求
     * @param url
     * @param headers
     * @param params
     * @param clzss
     * @return
     */
    public static <T> ResponseEntity<T> get(String url, HttpHeaders headers, Map<String, Object> params, Class<T> clzss){
        headers = headers == null?new HttpHeaders():headers;
        params = params == null? new HashMap<>():params;
        ResponseEntity<T> responseEntity = restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<String>(headers),
                clzss, params);
        return responseEntity;
    }

    /**
     * 发送http请求
     * @param url
     * @param headers
     * @param params
     * @param clzss
     * @return
     */
    public static <T> ResponseEntity<T> post(String url, HttpHeaders headers, Map<String, Object> params,Class<T> clzss){
        headers = headers == null?new HttpHeaders():headers;
        params = params == null? new HashMap<>():params;

        MultiValueMap<String, String> mparams= new LinkedMultiValueMap<>();
        //  也支持中文
        for (Map.Entry<String, Object> stringObjectEntry : params.entrySet()) {
            Object value = stringObjectEntry.getValue();
            if(value != null) {
                mparams.add(stringObjectEntry.getKey(), String.valueOf(value));
            }
        }
        HttpEntity<String> entity = new HttpEntity(mparams, headers);
        ResponseEntity<T> responseEntity = restTemplate.postForEntity(url, entity,
                clzss);
        return responseEntity;
    }

    public static void main(String[] args) {
        XxlJobUtils.init("http://127.0.0.1:8080/xxl-job-admin","admin","123456","dddddd");
//        XxlJobInfo xxlJobInfo = XxlJobUtils.addJob("dddddd", "test创建", "0 0 0 * * ? *", "testHandler", "", "hada", "754781341@qq.com");

        XxlJobUtils.updateJob(5,"1 0 0 * * ? *");
        System.out.println();



    }

}
